昨天我們使用了 Go 內建的 net/http
建立了 POST
和 GET
的 API 範例。今天我們會使用 Go 的 Gin 框架來建立 API,在實作的過程中,可以看一下兩種方式的差異。
其實用 Gin 框架來寫 API 會比單純使用 Go 內建的 net/http
方式還容易!
因為 Gin 的設計就是主打「 高效能 」和「 容易使用(上手) 」,它簡化了不少 HTTP 的任務,像是 JSON 編/解碼、錯誤處理等,光是這些功能的簡化就可以用比較少的程式來完成 API 了!
在開始之前,先來安裝 Gin 框架!大家還記得怎麼安裝嗎?我們在 Day 2 介紹 Go 基本語法的時候,有示範怎麼安裝套件,只是當時安裝完後就刪除套件了~
現在我們要再來安裝一次!
在 Go 專案底下輸入:
go get -u github.com/gin-gonic/gin
安裝完成後,你會看到 go.mod
檔案裡面多了 require,裡面包含 Gin 框架的一些套件,這樣就表示已經安裝成功了!
再來,要在 main.go
檔案裡 import Gin 框架(github.com/gin-gonic/gin
):
import (
"net/http"
"github.com/gin-gonic/gin"
)
這樣引入就可以了唷!
成功安裝 Gin 框架之後,我們就要來實作 API ~
首先,跟昨天的一開始一樣,我們需要先定義 User struct, 並預先建立一些假資料放進去。
然後會實作一個 GET、一個 POST 給大家看看
GET /users
:回傳使用者列表。POST /users
:建立新使用者。建立 User struct:
// 建立 User struct
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
建立假資料:
// 放入一些假資料
var users = []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
}
建立 GET
、POST
function:
// GET /users
func getUsers(c *gin.Context) {
c.JSON(http.StatusOK, users)
}
// POST /users
func addUser(c *gin.Context) {
var newUser User
if err := c.ShouldBindJSON(&newUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
newUser.ID = len(users) + 1
users = append(users, newUser)
c.JSON(http.StatusOK, newUser)
}
從以上的範例可以看到,在 Gin 框架中,它有 http.Status…
表示 API 回傳的狀態。基本上,從 Gin 的一些用法所使用的文字就可以知道大概在做什麼功能了,這就是 Gin 厲害的地方!它的設計真的淺顯易懂~
完整版 main.go
程式:
// 完整版 main.go
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
var users = []User{
{ID: 1, Name: "Alice"},
{ID: 2, Name: "Bob"},
}
func getUsers(c *gin.Context) { // GET /users
c.JSON(http.StatusOK, users)
}
func addUser(c *gin.Context) { // POST /users
var newUser User
if err := c.ShouldBindJSON(&newUser); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
newUser.ID = len(users) + 1
users = append(users, newUser)
c.JSON(http.StatusOK, newUser)
}
func main() {
r := gin.Default() // 建立 Gin
r.GET("/users", getUsers) // 註冊路由
r.POST("/users", addUser)
r.Run(":8080") // 啟動 server
}
是不是看起來很乾淨俐落!程式碼也減少了很多,而且從 function 的字面上更容易看懂這個程式在做什麼?
完成之後,我們就來測試看看 API 吧!
測試方式一樣是 使用終端機 來「 新增 」和「 查詢 」使用者。
一開始跟昨天一樣,先輸入指令,把 server 開起來:
// 啟動 server
go run main.go
但不一樣的是,輸出內容變多了!是 Gin 針對我們上述寫的 API 給了一些修改建議,這部分可以先看看,後續我們會再優化~
輸出:
測試 GET /users
,輸入:
curl http://localhost:8080/users
回傳:
[{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]
這個輸入、輸出的內容跟昨天的差不多,不一樣的是,當我們輸入指令之後,在剛剛我們輸入 go run main.go
的地方,多了這個 GET 請求 的輸出:
測試 POST /users
,輸入:
curl -X POST http://localhost:8080/users \
-H "Content-Type: application/json" \
-d '{"name":"Charlie"}'
回傳:
{"id":3,"name":"Charlie"}
然後,我們再去剛剛我們輸入 go run main.go
的地方,會發現它多了這個 POST 新增 的輸出:
以上就是使用 Gin 框架實作 API ~ 大家看完是不是覺得比昨天的內容簡單很多!